(function (content) {
  class Promise {
    constructor(excutor) {
      this.status = 'pending'
      this.data = null
      this.callbacks = []
      const _this = this

      function resolve (value) {
        if (_this.status !== 'pending') return
        _this.status = 'resolved'
        _this.data = value
        if (_this.callbacks.length) {
          setTimeout(() => {
            _this.callbacks.forEach(item => {
              item.onResolved(value)
            })
          })
        }
      }

      function reject (reason) {
        if (_this.status !== 'pending') return
        _this.status = 'rejected'
        _this.data = reason
        if (_this.callbacks.length) {
          setTimeout(() => {
            _this.callbacks.forEach(item => {
              item.onRejected(reason)
            })
          })
        }
      }

      try {
        excutor(resolve, reject)
      } catch (error) {
        reject(error)
      }
    }

    then (onResolved, onRejected) {
      if (typeof onResolved !== 'function') {
        onResolved = value => value
      }
      if (typeof onRejected !== 'function') {
        onRejected = err => { throw err }
      }
      const _this = this
      return new Promise((resolve, reject) => {
        function handle (callback) {
          try {
            const result = callback(_this.data)
            if (result instanceof Promise) {
              result.then(resolve, reject)
            } else {
              resolve(result)
            }
          } catch (error) {
            reject(error)
          }
        }
        if (this.status === 'pending') {
          this.callbacks.push({
            onResolved (value) {
              handle(onResolved)
            },
            onRejected (reason) {
              handle(onResolved)
            }
          })
        } else if (this.status === 'resolved') {
          setTimeout(() => {
            handle(onResolved)
          })
        } else {
          setTimeout(() => {
            handle(onRejected)
          })
        }
      })
    }

    catch (onRejected) {
      return this.then(null, onRejected)
    }

    static resolve (value) {
      return new Promise((resolve, reject) => {
        if (value instanceof Promise) {
          value.then(resolve, reject)
        } else {
          resolve(value)
        }
      })
    }

    static reject (reason) {
      return new Promise((resolve, reject) => {
        reject(reason)
      })
    }

    static all (promises) {
      let values = new Array(promises.length)
      let step = 0
      return new Promise((resolve, reject) => {
        promises.forEach((item, index) => {
          item.then(value => {
            step++
            values[index] = value
            if (step === promises.length) {
              resolve(values)
            }
          }, reason => {
            reject(reason)
          })
        })
      })
    }

    static race (promises) {
      return new Promise((resolve, reject) => {
        promises.forEach(item => {
          item.then(value => {
            resolve(value)
          }, reason => {
            reject(reason)
          })
        })
      })
    }

    static resolvedDelay (value, time) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          if (value instanceof Promise) {
            value.then(resolve, reject)
          } else {
            resolve(value)
          }
        }, time)
      })
    }

    static rejectedDelay (reason, time) {
      return Promise((resolve, reject) => {
        setTimeout(() => {
          reject(reason)
        }, time)
      })
    }
  }
})(window)